#include "CudaEpiModel.h"
#include "CudaParam.h"

void cudaNight(){
	thrust::device_vector<int> mutex(4,0);
	thrust::device_vector<int> TAP_mutex_1(model->nNumCommunities,0);
	thrust::device_vector<int> TAP_mutex_2(1,0);
	
	time_t start = clock();
	
	thrust::for_each(comm_vec->begin(),comm_vec->end(),
		NightOp(thrust::raw_pointer_cast(ppl_vec->data()),
				thrust::raw_pointer_cast(tract_vec->data()),
				thrust::raw_pointer_cast(comm_vec->data()),
				thrust::raw_pointer_cast(rand_vec->data()),
				
				model->nTimer,model->AVEp,
				model->fSymptomaticAscertainment,model->bTrigger,
				model->fLiberalLeaveCompliance,model->fIsolationCompliance,
				model->fQuarantineCompliance,model->bTravel,model->nAscertainmentDelay,
				model->fContactAscertainment,
				
				nNumTAPDone,nNumWantAV,
				
				thrust::raw_pointer_cast(comm_visitor_vec->data()),
				thrust::raw_pointer_cast(comm_visitor_start_vec->data()),
				thrust::raw_pointer_cast(comm_visitor_end_vec->data()),
				
				thrust::raw_pointer_cast(mutex.data()),
				thrust::raw_pointer_cast(TAP_mutex_1.data()),
				thrust::raw_pointer_cast(TAP_mutex_2.data()))
				);
				
	err = cudaThreadSynchronize();
        if(err != cudaSuccess) cout << "cudaThreadSynchronize error: " << cudaGetErrorString(err) << endl;
		
	cout << "night op: " << ((double)clock() - start)/ CLOCKS_PER_SEC << endl;	

		
}

__device__ void nightInfectSusceptibles(
	const dPerson& infected,dCommunity& comm,
	dPerson* ppl_vec,dCommunity* comm_vec,RandGen* rand_vec,
	int timer,	
	double AVEp,
	double fSymptomaticAscertainment,
	int bTrigger,
	double fLiberalLeaveCompliance,
	double fIsolationCompliance,
	bool bTravel,
	dCommVisitor* comm_visitor_vec, unsigned int comm_visitor_start_idx, unsigned int comm_visitor_end_idx,
	int* mutex, int target_value){
	
	const double *cpf = (dPerson::isChild(infected)?dcpfc:dcpfa); // probability of family transmission
	const double *cphc = (dPerson::isChild(infected)?dcphcc:dcphca); // probability of household cluster transmission
	
	for (unsigned int pid2=comm.nFirstPerson; pid2<comm.nLastPerson; pid2++) {
		dPerson &p2 = ppl_vec[pid2];
		if (dPerson::isSusceptible(p2) && p2.nTravelTimer<=0) { // && p.id!=p2.id) {
			if (infected.family==p2.family){
				InfectOp new_infect1(p2,infected,cpf[p2.age],FROMFAMILYNIGHT,
									rand_vec[comm.id],timer,AVEp,
									fSymptomaticAscertainment,bTrigger,fLiberalLeaveCompliance,
									fIsolationCompliance,comm_vec);
			
				if (new_infect1.infect()) continue;
			}
			if (!dPerson::isWithdrawn(infected) && 
			!dPerson::isQuarantined(infected) && !dPerson::isQuarantined(p2)) {
				InfectOp new_infect2(p2,infected,comm.cpcm[p2.age],FROMCOMMUNITYNIGHT,
									rand_vec[comm.id],timer,AVEp,
									fSymptomaticAscertainment,bTrigger,fLiberalLeaveCompliance,
									fIsolationCompliance,comm_vec);
									
				if (!new_infect2.infect()) { // transmission within home community
					if (infected.nHomeNeighborhood==p2.nHomeNeighborhood){ // transmission within neighborhood
						InfectOp new_infect3(p2,infected,comm.cpnh[p2.age],FROMNEIGHBORHOODNIGHT,
											rand_vec[comm.id],timer,AVEp,
											fSymptomaticAscertainment,bTrigger,fLiberalLeaveCompliance,
											fIsolationCompliance,comm_vec);
					
						if (new_infect3.infect()) continue;
					}
					if (infected.householdcluster==p2.householdcluster){ // transmission within household cluster
						InfectOp new_infect4(p2,infected,cphc[p2.age],FROMHHCLUSTERNIGHT,
											rand_vec[comm.id],timer,AVEp,
											fSymptomaticAscertainment,bTrigger,fLiberalLeaveCompliance,
											fIsolationCompliance,comm_vec);
						new_infect4.infect();
					}
				}
			}
		}
	}
	
	Barrier(mutex,target_value);
	
	// check for susceptible travelers
	if (bTravel) {
  
		for (unsigned int i = comm_visitor_start_idx; i < comm_visitor_end_idx; i++) {
			dPerson &p2 = comm_visitor_vec[i].visitor;
			if (dPerson::isSusceptible(p2)) {
				if (infected.family==p2.family){  // transmission within household
					InfectOp new_infect1(p2,infected,cpf[p2.age],FROMFAMILY,
										rand_vec[comm.id],timer,AVEp,
										fSymptomaticAscertainment,bTrigger,fLiberalLeaveCompliance,
										fIsolationCompliance,comm_vec);
					
					if (new_infect1.infect()) continue;
				}
				if (!dPerson::isWithdrawn(infected) 
				&& !dPerson::isQuarantined(infected) && !dPerson::isQuarantined(p2)) {
					InfectOp new_infect2(p2,infected,comm.cpcm[p2.age],FROMCOMMUNITYNIGHT,
										rand_vec[comm.id],timer,AVEp,
										fSymptomaticAscertainment,bTrigger,fLiberalLeaveCompliance,
										fIsolationCompliance,comm_vec);
					
					if (!new_infect2.infect()) { // transmission within home community
						if (infected.nHomeNeighborhood==p2.nHomeNeighborhood){ // transmission within neighborhood
							InfectOp new_infect3(p2,infected,comm.cpnh[p2.age],FROMNEIGHBORHOODNIGHT,
												rand_vec[comm.id],timer,AVEp,
												fSymptomaticAscertainment,bTrigger,fLiberalLeaveCompliance,
												fIsolationCompliance,comm_vec);

							if (new_infect3.infect()) continue;
						}
						if (infected.householdcluster==p2.householdcluster){ // transmission within household cluster
							InfectOp new_infect4(p2,infected,cphc[p2.age],FROMHHCLUSTERNIGHT,
												rand_vec[comm.id],timer,AVEp,
												fSymptomaticAscertainment,bTrigger,fLiberalLeaveCompliance,
												fIsolationCompliance,comm_vec);
							
							new_infect4.infect();
						}
					}
				}
			}
		}
	}
	
	Barrier(mutex+1,target_value);
}